1 module hip.game2d.threepatch; 2 3 public import hip.api.renderer.texture; 4 public import hip.game2d.sprite; 5 import hip.api.renderer.shaders.spritebatch; 6 import hip.api.data.textureatlas; 7 8 enum ThreePatchOrientation 9 { 10 horizontal, 11 vertical, 12 inferred 13 } 14 15 16 final class ThreePatch 17 { 18 int x, y; 19 int width, height; 20 HipSpriteVertex[4*3] vertices; 21 HipSprite[3] sprites; 22 protected ThreePatchOrientation orientation = ThreePatchOrientation.inferred; 23 24 protected this(IHipTexture tex, ThreePatchOrientation o) 25 { 26 foreach(i; 0..3) 27 { 28 sprites[i] = new HipSprite(tex); 29 sprites[i].setOrigin(0,0); 30 } 31 this.orientation = o == ThreePatchOrientation.inferred ? infer(tex) : o; 32 } 33 34 pragma(inline) ThreePatchOrientation getOrientation() 35 { 36 return orientation; 37 } 38 void setOrientation(ThreePatchOrientation ori = ThreePatchOrientation.horizontal) 39 { 40 if(ori == ThreePatchOrientation.inferred) 41 ori = infer(this.sprites[0].getTexture); 42 if(ori != orientation) 43 { 44 orientation = ori; 45 build(); 46 } 47 } 48 49 /** 50 * 51 * Params: 52 * rects = The regions that is used as reference for this three patch 53 * tex = Texture reference for the regions 54 * width = Width of the resulting threepatch 55 * height = Height of the resulting threepatch 56 * o = Orientation of the threepatch, default is inferred. 57 * Returns: 58 */ 59 static ThreePatch fromQuads(AtlasRect[3] rects, IHipTexture tex, int width, int height, ThreePatchOrientation o = ThreePatchOrientation.inferred) 60 { 61 ThreePatch t = new ThreePatch(tex, o); 62 AtlasSize sz = AtlasSize(tex.getWidth, tex.getHeight); 63 foreach(i; 0..3) 64 t.sprites[i].setRegion(rects[i].toQuad(sz)); 65 t.setSize(width, height); 66 return t; 67 } 68 69 /** 70 * 71 * Params: 72 * tex = Takes a texture, divide it into 3 [depending on orientation], and assemble the threepatch 73 * width = Width of the resulting texture 74 * height = Height of the resulting texture 75 * o = Orientation of the threepatch, default is inferred. 76 * Returns: 77 */ 78 static ThreePatch fromTexture(IHipTexture tex, int width, int height, ThreePatchOrientation o = ThreePatchOrientation.inferred) 79 { 80 ThreePatch ret = new ThreePatch(tex, o); 81 82 int w = tex.getWidth; 83 int h = tex.getHeight; 84 85 if(o == ThreePatchOrientation.inferred) 86 o = w >= h ? ThreePatchOrientation.horizontal : ThreePatchOrientation.vertical; 87 88 if(o == ThreePatchOrientation.horizontal) 89 { 90 float rw = cast(float)w/3; 91 ret.sprites[0].setRegion(0, 0, rw, 1.0); 92 ret.sprites[1].setRegion(rw, 0, rw*2, 1.0); 93 ret.sprites[2].setRegion(rw*2, 0, rw*3, 1.0); 94 } 95 else 96 { 97 float rh = cast(float)h/3; 98 ret.sprites[0].setRegion(0, 0, rh, 1.0); 99 ret.sprites[1].setRegion(rh, 0, rh*2, 1.0); 100 ret.sprites[2].setRegion(rh*2, 0, rh*3, 1.0); 101 } 102 ret.setSize(width, height); 103 return ret; 104 } 105 106 void setSize(int width, int height) 107 { 108 this.width = width; 109 this.height = height; 110 build(); 111 } 112 113 protected void updatePosition() 114 { 115 if(getOrientation == ThreePatchOrientation.horizontal) 116 { 117 sprites[0].setPosition(x, y); 118 sprites[1].setPosition(x+sprites[0].width, y); 119 sprites[2].setPosition(x+width - (sprites[2].width), y); 120 } 121 else 122 { 123 sprites[0].setPosition(x, y); 124 sprites[1].setPosition(x, y + sprites[0].getHeight); 125 sprites[2].setPosition(x, y + height - sprites[2].height); 126 } 127 } 128 129 void build() 130 { 131 import hip.api; 132 updatePosition(); 133 if(getOrientation == ThreePatchOrientation.horizontal) 134 { 135 int spWidth = sprites[0].getWidth+sprites[2].getWidth; 136 float xScalingFactor = cast(float)(width - spWidth) / sprites[1].getWidth; 137 sprites[1].setScale(xScalingFactor, 1); 138 } 139 else 140 { 141 int spHeight = sprites[0].getHeight+sprites[2].getHeight; 142 float yScalingFactor = cast(float)(height - spHeight) / sprites[1].getHeight; 143 144 sprites[1].setScale(1, yScalingFactor); 145 } 146 147 148 } 149 150 void draw() 151 { 152 import hip.api; 153 foreach(sp; sprites) 154 sp.draw; 155 } 156 157 158 159 void setPosition(int x, int y) 160 { 161 this.x = x; 162 this.y = y; 163 updatePosition(); 164 } 165 166 ref HipSpriteVertex[4*3] getVertices(){return vertices;} 167 168 } 169 170 private ThreePatchOrientation infer(int width, int height){return width > height ? ThreePatchOrientation.horizontal : ThreePatchOrientation.vertical;} 171 private ThreePatchOrientation infer(const IHipTexture tex){return tex.getWidth > tex.getHeight ? ThreePatchOrientation.horizontal : ThreePatchOrientation.vertical;} 172 173 174 /** 175 * 0 1 2 176 * ________ 177 * |________| 178 * 179 * 180 * ___ 181 * | | 0 182 * | | 1 183 * |___| 2 184 */